﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Mvc;
using RayD.Core;
using RayD.Repository.Entites.SystemModule;
using RayD.App.SystemModule;
using RayD.WebApi.Models;

namespace RayD.WebApi.Controllers
{
    /// <summary>
    /// 登录资源
    /// </summary>
    [Route("api/[controller]/[action]")]
    public class LoginController : BaseController
    {
        #region 构造函数注入
        private UserApp _userService;
        private UserRelationApp _userRelationService;
        private ManaframeApp _manaframeService;
        private DepartmentApp _departmentService;
        public LoginController(UserApp userService
            , UserRelationApp userRelationService
            , ManaframeApp manaframeService
            , DepartmentApp departmentService)
        {
            this._userService = userService;
            this._userRelationService = userRelationService;
            this._manaframeService = manaframeService;
            this._departmentService = departmentService;
        }
        #endregion

        #region 参数实体
        /// <summary>
        /// 登录接口请求参数
        /// </summary>
        public class GetJwtRequest : BaseModel
        {
            /// <summary>
            /// 账号
            /// </summary>
            public string account { get; set; }
            /// <summary>
            /// 密码 MD5 32位 小写
            /// </summary>
            public string password { get; set; }
            /// <summary>
            /// 客户端拖动滑块轨迹
            /// </summary>
            public List<int> trackArr { get; set; }

            /// <summary>
            /// 数据安全校验
            /// </summary>
            /// <returns></returns>
            public override void CheckParameter()
            {
                base.CheckParameter();
                //自定义参数校验
            }
        }
        /// <summary>
        /// 请求刷新Token（以旧换新）请求参数
        /// </summary>
        public class RefreshTokenRequest : BaseModel
        {
            /// <summary>
            /// 过期或可用的JWT
            /// </summary>
            public string token { get; set; }

            /// <summary>
            /// 数据安全校验
            /// </summary>
            /// <returns></returns>
            public override void CheckParameter()
            {
                base.CheckParameter();
                //自定义参数校验
                if (string.IsNullOrEmpty(this.token))
                {
                    throw new Exception("token无效，请重新登录！");
                }
            }
        }
        /// <summary>
        /// 登录接口响应参数
        /// </summary>
        public class JwtRespone
        {
            /// <summary>
            /// Token字符串
            /// </summary>
            public string token { get; set; }
            /// <summary>
            /// Token类型
            /// </summary>
            public string token_Type { get; set; }
            /// <summary>
            /// Token过期时间（分钟）
            /// </summary>
            public double? expires_in { get; set; }
        }
        /// <summary>
        /// 验证码接口响应参数
        /// </summary>
        public class VcodeRespone
        {
            /// <summary>
            /// Base64格式图片
            /// </summary>
            public string img { get; set; }
            /// <summary>
            /// 验证码标识
            /// </summary>
            public string vcodeToken { get; set; }
        }
        #endregion

        #region 获取数据
        /// <summary>
        /// 获取验证码（已改用滑块验证）
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ResParameter<VcodeRespone> GetVerifyCode()
        {
            string chkCode = VerifyCodeHelper.CreateRandomText();
            var data = new VcodeRespone()
            {
                img = VerifyCodeHelper.CreateBase64Image(chkCode),
                vcodeToken = Guid.NewGuid().ToString()
            };
            CacheHelper.LocalCache.SetCache(data.vcodeToken, Md5Helper.Encrypt(chkCode.ToLower(), 16), TimeSpan.FromMinutes(Define.EXPIRETIME), ExpireType.Relative);
            return Success(data);
        }
        /// <summary>
        /// 获取JWT
        /// </summary>
        /// <returns></returns>
        [HttpPost, Logging("用户登录")]
        public ResParameter<JwtRespone> GetJwt(GetJwtRequest param)
        {
            //参数校验
            param.CheckParameter();

            #region 滑块验证码验证
            var sum = param.trackArr.Sum();
            var avg = sum * 1.0 / param.trackArr.Count;
            var stddev = param.trackArr.Select(v => Math.Pow(v - avg, 2)).Sum() / param.trackArr.Count;
            if(stddev == 0)
            {
                //登录失败
                return Fail("安全验证失败！", new JwtRespone());
            }
            #endregion

            //账户认证
            (bool LoginOk, string LoginMsg) = _userService.CheckLogin(param.account, param.password);

            if (LoginOk)
            {
                #region 初始化用户所有数据
                UserInfo userInfo = new UserInfo();
                UserEntity userEntity = _userService.GetEntityByAccount(param.account);
                userInfo.userId = userEntity.B_UserId;
                userInfo.account = userEntity.B_Account;
                userInfo.enCode = userEntity.B_EnCode;
                userInfo.realName = userEntity.B_RealName;
                userInfo.headIcon = userEntity.B_HeadIcon;
                userInfo.gender = userEntity.B_Gender;
                userInfo.birthday = userEntity.B_Birthday;
                userInfo.mobile = userEntity.B_Mobile;
                userInfo.telephone = userEntity.B_Telephone;
                userInfo.email = userEntity.B_Email;
                userInfo.oICQ = userEntity.B_OICQ;
                userInfo.weChat = userEntity.B_WeChat;
                userInfo.manaframeId = userEntity.B_ManaframeId;
                userInfo.departmentId = userEntity.B_DepartmentId;
                //权限关联
                userInfo.isSystem = userEntity.B_SecurityLevel == 1 ? true : false;
                userInfo.roleIds = _userRelationService.GetObjectIds(userEntity.B_UserId, "1");
                userInfo.postIds = _userRelationService.GetObjectIds(userEntity.B_UserId, "2");
                //架构关联
                //userInfo.manaframeIds = _manaframeService.GetSubNodes(userEntity.B_ManaframeId);
                //userInfo.departmentIds = _departmentService.GetSubNodes(userEntity.B_ManaframeId, userEntity.B_DepartmentId);
                //唯一SID
                var Sid = Guid.NewGuid().ToString();
                #endregion

                //记录JWT
                var dict = new Dictionary<string, string>();
                dict.Add(ClaimTypes.Sid, Sid);
                dict.Add(ClaimTypes.UserData, userInfo.ToJson());
                var jwt = JwtHelper.BuildJwtToken(dict);

                //登录成功
                return Success(LoginMsg, new JwtRespone()
                {
                    token_Type = "Bearer",
                    token = jwt,
                    expires_in = AppSettings.Jwt.ExpireTime
                });
            }
            else
            {
                //登录失败
                return Fail(LoginMsg, new JwtRespone());
            }

        }
        /// <summary>
        /// 请求刷新Token（以旧换新）
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ResParameter<JwtRespone> RefreshToken(RefreshTokenRequest param)
        {
            //参数校验
            param.CheckParameter();

            var claimDict = JwtHelper.SerializeJwt(param.token);
            if (claimDict.Count > 0)
            {
                //当前登录用户信息
                var userInfo = claimDict.GetValueOrDefault(ClaimTypes.UserData)?.ToObject<UserInfo>() ?? new UserInfo();

                #region 重载用户所有数据
                UserEntity userEntity = _userService.GetEntityById(userInfo.userId);
                userInfo.userId = userEntity.B_UserId;
                userInfo.account = userEntity.B_Account;
                userInfo.enCode = userEntity.B_EnCode;
                userInfo.realName = userEntity.B_RealName;
                userInfo.headIcon = userEntity.B_HeadIcon;
                userInfo.gender = userEntity.B_Gender;
                userInfo.birthday = userEntity.B_Birthday;
                userInfo.mobile = userEntity.B_Mobile;
                userInfo.telephone = userEntity.B_Telephone;
                userInfo.email = userEntity.B_Email;
                userInfo.oICQ = userEntity.B_OICQ;
                userInfo.weChat = userEntity.B_WeChat;
                userInfo.manaframeId = userEntity.B_ManaframeId;
                userInfo.departmentId = userEntity.B_DepartmentId;
                //权限关联
                userInfo.isSystem = userEntity.B_SecurityLevel == 1 ? true : false;
                userInfo.roleIds = _userRelationService.GetObjectIds(userEntity.B_UserId, "1");
                userInfo.postIds = _userRelationService.GetObjectIds(userEntity.B_UserId, "2");
                //架构关联
                //userInfo.manaframeIds = _manaframeService.GetSubNodes(userEntity.B_ManaframeId);
                //userInfo.departmentIds = _departmentService.GetSubNodes(userEntity.B_ManaframeId, userEntity.B_DepartmentId);
                //唯一SID
                var Sid = Guid.NewGuid().ToString();
                #endregion

                //记录JWT
                var dict = new Dictionary<string, string>();
                dict.Add(ClaimTypes.Sid, Sid);
                dict.Add(ClaimTypes.UserData, userInfo.ToJson());
                var refreshToken = JwtHelper.BuildJwtToken(dict);

                return Success("获取成功", new JwtRespone()
                {
                    token_Type = "Bearer",
                    token = refreshToken,
                    expires_in = AppSettings.Jwt.ExpireTime
                });
            }
            return Fail("认证失败！", new JwtRespone());
        }
        #endregion

    }
}
